﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RWLib
{
    public class FluentEffectStatement : StatementBase
    {

        private Formula condition;
        private Fluent effects;
        private Formula _effects;

        public FluentEffectStatement(string _name, Formula _condition, Formula effects)
        {
            condition = _condition;
            _effects = effects;
            name = _name;
        }

        public Formula Effects {
            get { return _effects; }
        }

        public Formula Condition
        {
            get { return condition; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fluents"></param>
        /// <returns>Zwraca listę nowych stanów, jeżeli wyrażenie condition ma wartość true</returns>
        public override List<List<Fluent>> Run(List<Fluent> state)
        {            
            List<List<Fluent>> states =new List<List<Fluent>>();
            bool imp = false;
            if (ImpossibleCondition != null) {
                if (ImpossibleCondition.Eval(state)) {
                    imp = true;
                }
            }
            if (condition == null || condition.Eval(state) && (!imp))
            {
                performed = true;
                List<List<Fluent>> perm = _effects.Fluents.Permutates().Where(l => _effects.Eval(l)).ToList();
                perm.ForEach(l =>
                {
                    l.ForEach(ll =>
                    {
                        ll.Changed = true;
                    });
                    l.AddRange(state.Where(s => !l.Contains(s.Name)));
                });
                states = perm;
            }
            else {
                states.Add(state.Copy());
                performed = false;
            }
            if (StartTime >= Tree.currentTime)
            {
                if (TriggeredBy != null)
                {
                    TriggeredBy.release(this);
                }
            }
            return states;
        }

        public override bool Conflict(StatementBase action, List<Fluent> state)
        {
            if (action is FluentEffectStatement)
            {
                FluentEffectStatement tmp = action as FluentEffectStatement;

                if (!tmp.Condition.Eval(state) || !this.Condition.Eval(state))
                {
                    return false;
                }

                tmp.Effects.Eval(state);
                this.Effects.Eval(state);

                return tmp.Effects.Conflicts(this.Effects);
            }
            else if (action is ReleaseStatement)
            {
                ReleaseStatement tmp = action as ReleaseStatement;
                string tname = tmp.Effects.Name;
                return this.Effects.Fluents.Any(f => tmp.Effects.Name.Equals(f.Name));
            }
            return false;
        }

        public override string ToString()
        {
            var sb=new StringBuilder();
            sb.Append(name);
            sb.Append(" causes (");
            sb.Append(_effects.ToString());
            sb.Append(")");
            sb.Append(" if (");
            sb.Append(condition.ToString());
            sb.Append(") Impossible:");
            sb.Append(ImpossibleCondition);
            return sb.ToString();
        }
    }

}
